package com.bigfans.cartservice.service.impl;

import com.bigfans.cartservice.model.Cart;
import com.bigfans.cartservice.model.CartItem;
import com.bigfans.framework.exception.ServiceRuntimeException;
import com.bigfans.framework.redis.JedisConnection;
import com.bigfans.framework.redis.JedisExecuteCallback;
import com.bigfans.framework.redis.JedisExecuteWithoutReturnCallback;
import com.bigfans.framework.redis.JedisTemplate;
import com.bigfans.framework.utils.StringHelper;
import org.springframework.util.Assert;

import java.util.*;


/**
 * 
 * @Title: 
 * @Description: Redis的业务逻辑
 * @author lichong 
 * @date 2016年2月1日 上午9:24:01 
 * @version V1.0
 */
public class RedisService {
	
	private Integer DB_INDEX = 1;

	private String DB_PREFIX = "cart:";

	private static final int DAYS_30 = 60 * 60 * 24 * 30;

	public JedisTemplate jedisTemplate;

	public RedisService(JedisTemplate jedisTemplate) {
		this.jedisTemplate = jedisTemplate;
	}

	public void setDB_INDEX(Integer DB_INDEX) {
		this.DB_INDEX = DB_INDEX;
	}

	public void setDB_PREFIX(String DB_PREFIX) {
		this.DB_PREFIX = DB_PREFIX;
	}

	public void addItem(final String userKey , final String pid , final Integer amount){
		Assert.notNull(userKey);
		jedisTemplate.executeInPipeline(new JedisExecuteWithoutReturnCallback() {
			public void runInConnection(JedisConnection conn) {
				String key = DB_PREFIX + userKey;
				conn.selectDB(DB_INDEX);
				String dbcount = conn.hget(key, pid);
				if(dbcount == null){
					conn.hset(key, pid, String.valueOf(amount));
				}else{
					conn.hincrBy(key, pid, new Long(amount));
				}
			}
		});
	}
	
	public List<CartItem> getCartItems(final String userKey){
		Assert.notNull(userKey);
		List<CartItem> items = jedisTemplate.execute(new JedisExecuteCallback<List<CartItem>>() {
			@Override
			public List<CartItem> runInConnection(JedisConnection conn) {
				String key = DB_PREFIX + userKey;
				conn.selectDB(DB_INDEX);
				Map<String, String> hash = conn.hgetAll(key);
				ArrayList<CartItem> cartItems = new ArrayList<CartItem>();
				for (Map.Entry<String, String> entry : hash.entrySet()) {
					String pid = entry.getKey();
					Integer quantity = Integer.valueOf(entry.getValue());
					CartItem cartItem = new CartItem();
					cartItem.setProdId(pid);
					cartItem.setQuantity(Math.abs(quantity));
					if(quantity >0){
						cartItem.setIsSelected(true);
					}else {
						cartItem.setIsSelected(false);
					}
					cartItems.add(cartItem);
				}
				return cartItems;
			}
		});
		return items;
	}
	
	public Cart cartSummary(final String userKey , int count) throws ServiceRuntimeException {
		Assert.notNull(userKey);
		Assert.isTrue(count > 0);
		Cart cart = myCart(userKey);
		List<CartItem> cartItems = cart.getItems();
		Collections.sort(cartItems, new Comparator<CartItem>() {
			@Override
			public int compare(CartItem o1, CartItem o2) {
				return o1.getCreateDate().compareTo(o2.getCreateDate());
			}
		});
		cart.setItems(cartItems.subList(0, cartItems.size()>count ? count : cartItems.size()));
		return cart;
	}
	
	public Cart myCart(final String userKey) throws ServiceRuntimeException {
		Assert.notNull(userKey);
		Cart cart = new Cart();
		cart.setItems(getCartItems(userKey));
		return cart;
	}
	
	public Integer sumMyCart(final String userKey){
		if(StringHelper.isEmpty(userKey)){
			return 0;
		}
		return jedisTemplate.execute(new JedisExecuteCallback<Integer>() {
			@Override
			public Integer runInConnection(JedisConnection conn) {
				String key = DB_PREFIX + userKey;
				conn.selectDB(DB_INDEX);
				List<String> hvals = conn.hvals(key);
				Integer totalCount = 0;
				for (String count : hvals) {
					totalCount += Math.abs(Integer.valueOf(count));
				}
				return totalCount;
			}
		});
	}
	
	public void removeCart(final String userKey) {
		Assert.notNull(userKey);
		jedisTemplate.executeInPipeline(new JedisExecuteWithoutReturnCallback() {
			public void runInConnection(JedisConnection conn) {
				conn.selectDB(DB_INDEX);
				conn.del(DB_PREFIX + userKey);
			}
		});
	}
	
	public void updateAmount(final String userKey , final String pid , final Integer currentAmount){
		Assert.notNull(userKey);
		jedisTemplate.executeInPipeline(new JedisExecuteWithoutReturnCallback() {
			public void runInConnection(JedisConnection conn) {
				String key = DB_PREFIX + userKey;
				conn.selectDB(DB_INDEX);
				conn.hset(key, pid, String.valueOf(currentAmount));
			}
		});
	}
	
	public void selectCartItem(String userKey, String pid) {
		Assert.notNull(userKey);
		jedisTemplate.executeInPipeline(new JedisExecuteWithoutReturnCallback() {
			public void runInConnection(JedisConnection conn) {
				String key = DB_PREFIX + userKey;
				conn.selectDB(DB_INDEX);
				String amount = conn.hget(key, "amount");
				conn.hset(key, pid, String.valueOf(Math.abs(Integer.valueOf(amount))));
			}
		});
	}
	
	public void selectAllCartItems(String userKey) {
		
	}
	
	public void cancelCartItem(String userKey, String pid) {
		jedisTemplate.executeInPipeline(new JedisExecuteWithoutReturnCallback() {
			public void runInConnection(JedisConnection conn) {
				String key = DB_PREFIX + userKey;
				conn.selectDB(DB_INDEX);
				Integer amount = Integer.valueOf(conn.hget(key, "amount"));
				if(amount > 0){
					conn.hset(key, pid, String.valueOf(-amount));
				}
			}
		});
	}
	
	public void cancelAllCartItems(String userKey) {
		
	}
	
	public void removeCartItem(final String userKey , final String pid){
		jedisTemplate.execute(new JedisExecuteWithoutReturnCallback() {
			public void runInConnection(JedisConnection conn) {
				conn.selectDB(DB_INDEX);
				if(pid != null && !"".equals(pid)){
					conn.hdel(DB_PREFIX + userKey, pid);
				}else{
					conn.del(DB_PREFIX + userKey);
				}
			}
		});
	}
	
}
